#include<cstdio>//uncle-lu luogu.org 3373
#include<algorithm>
template<class T>void read(T &x)
{
	x=0;int f=0;char ch=getchar();
	while(ch<'0'||ch>'9') { f|=(ch=='-'); ch=getchar(); }
	while(ch<='9'&&ch>='0') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
	x = f ? -x : x;
	return ;
}

void Build_Tree(int, int, int);
void Add_Tree(int, const int, const int, int, int, int);
void Mulit_Tree(int, const int, const int, int, int, int);
void push_down(int, const int, const int);
int Find_Tree(int , const int, const int, int, int);

long long int Tree[400010], Lazy_Add[400010], Lazy_Mulit[400010], line[100010], Mod;
int n, m;

void Build_Tree(int step, int x, int y)
{
	Lazy_Mulit[step] = 1;
	if(x==y) { Tree[step] = line[x]; return ; }
	int mid = (x+y)>>1;
	Build_Tree(step<<1, x, mid);
	Build_Tree(step<<1|1, mid+1, y);
	Tree[step] = Tree[step<<1] + Tree[step<<1|1];
	return ;
}

void push_down(int step, int x, int y)
{
	int mid = (x+y)>>1;
	Tree[step<<1] = (Tree[step<<1] * Lazy_Mulit[step] + Lazy_Add[step] * (mid-x+1)) % Mod;
	Tree[step<<1|1] = (Tree[step<<1|1] * Lazy_Mulit[step] + Lazy_Add[step] * (y-mid)) % Mod;
	Lazy_Mulit[step<<1] = Lazy_Mulit[step<<1] * Lazy_Mulit[step] % Mod;
	Lazy_Mulit[step<<1|1] = Lazy_Mulit[step<<1|1] * Lazy_Mulit[step] % Mod;
	Lazy_Add[step<<1] = (Lazy_Add[step<<1] * Lazy_Mulit[step] + Lazy_Add[step]) % Mod;
	Lazy_Add[step<<1|1] = (Lazy_Add[step<<1|1] * Lazy_Mulit[step] + Lazy_Add[step]) % Mod;
	Lazy_Add[step] = 0;
	Lazy_Mulit[step] = 1;
	return ;
}

void Add_Tree(int step, const int l, const int r, int x, int y, long long int val)
{
	if(l<=x && y<=r)
	{
		Tree[step] = ( Tree[step] + val*(y-x+1) ) % Mod;
		Lazy_Add[step] = (Lazy_Add[step] + val) % Mod;
		return ;
	}
	
	push_down(step, x, y);
	int mid = (x+y)>>1;
	if(mid+1<=r)
		Add_Tree(step<<1|1, l, r, mid+1, y, val);
	if(l<=mid)
		Add_Tree(step<<1, l, r, x, mid, val);
	Tree[step] = (Tree[step<<1] + Tree[step<<1|1]) % Mod;
	return ;
}

void Mulit_Tree(int step, const int l, const int r, int x, int y, long long int val)
{
	if( l<=x && y<=r )
	{
		Tree[step] = Tree[step] * val % Mod;
		Lazy_Mulit[step] = Lazy_Mulit[step] * val % Mod;
		Lazy_Add[step] = Lazy_Add[step] * val % Mod;
		return ;
	}

	push_down(step, x, y);
	int mid = (x+y)>>1;
	if(mid+1<=r)
		Mulit_Tree(step<<1|1, l, r, mid+1, y, val);
	if(l<=mid)
		Mulit_Tree(step<<1, l, r, x, mid, val);
	Tree[step] = (Tree[step<<1] + Tree[step<<1|1]) % Mod;
	return ;
}

int Find_Tree(int step, const int l, const int r, int x, int y)
{
	if( l<=x && y<=r )
		return Tree[step];

	push_down(step, x, y);
	int mid = (x+y)>>1;
	int sum = 0;
	if(mid+1<=r)
		sum += Find_Tree(step<<1|1, l, r, mid+1, y);
	if(l<=mid)
		sum += Find_Tree(step<<1, l, r, x, mid);

	sum %= Mod;
	return sum;
}

int main()
{
	read(n);read(m);read(Mod);
	for(int i=1;i<=n;++i)
		read(line[i]);
	Build_Tree(1, 1, n);
	int temp, x, y;long long int k;
	for(int i=1;i<=m;++i)
	{
		read(temp);
		if(temp == 1)
		{
			read(x);read(y);read(k);
			Mulit_Tree(1, x, y, 1, n ,k);
		}
		else if(temp == 2)
		{
			read(x);read(y);read(k);
			Add_Tree(1, x, y, 1, n, k);
		}
		else if(temp == 3)
		{
			read(x);read(y);
			printf("%d\n",Find_Tree(1, x, y, 1, n));
		}
	}
	return 0;
}